home *** CD-ROM | disk | FTP | other *** search
/ Cream of the Crop 25 / Cream of the Crop 25.iso / os2 / gnuwget.zip / wget-1.4.3 / src / http.c < prev    next >
C/C++ Source or Header  |  1997-02-09  |  33KB  |  1,212 lines

  1. /* HTTP support.
  2.    Copyright (C) 1995, 1996, 1997 Free Software Foundation, Inc.
  3.    
  4.    This program is free software; you can redistribute it and/or modify
  5.    it under the terms of the GNU General Public License as published by
  6.    the Free Software Foundation; either version 2 of the License, or
  7.    (at your option) any later version.
  8.    
  9.    This program is distributed in the hope that it will be useful,
  10.    but WITHOUT ANY WARRANTY; without even the implied warranty of
  11.    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  12.    GNU General Public License for more details.
  13.    
  14.    You should have received a copy of the GNU General Public License
  15.    along with this program; if not, write to the Free Software
  16.    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.  */
  17.  
  18.  
  19. #ifdef HAVE_CONFIG_H
  20. #  include <config.h>
  21. #endif /* HAVE_CONFIG_H */
  22.  
  23. #include <stdio.h>
  24. #include <stdlib.h>
  25. #include <sys/types.h>
  26. #ifdef HAVE_UNISTD_H
  27. #  include <unistd.h>
  28. #endif
  29. #include <sys/stat.h>
  30. #ifdef HAVE_STRING_H
  31. #  include <string.h>
  32. #else
  33. #  include <strings.h>
  34. #endif
  35. #include <ctype.h>
  36. #include <assert.h>
  37.  
  38. #ifdef WINDOWS
  39. #  include <winsock.h>
  40. #endif
  41.  
  42. #include "wget.h"
  43. #include "options.h"
  44. #include "utils.h"
  45. #include "url.h"
  46. #include "host.h"
  47. #include "http.h"
  48. #include "retr.h"
  49. #include "connect.h"
  50. #include "mtch.h"
  51. #include "netrc.h"
  52.  
  53. extern char *version_string;
  54. extern struct options opt;
  55.  
  56. #ifndef errno
  57. extern int errno;
  58. #endif
  59. #ifndef h_errno
  60. extern int h_errno;
  61. #endif
  62.  
  63. /* Function to fetch a header from socket/file descriptor fd. The
  64.    header may be of arbitrary length, since the function allocates as
  65.    much memory as necessary for the header to fit. Most errors are
  66.    handled.
  67.  
  68.    The header may be terminated by LF or CRLF.  If the character after
  69.    LF is SP or HT (horizontal tab), the header spans to another line
  70.    (continuation header), as per RFC2068.
  71.  
  72.    The trailing CRLF or LF are stripped from the header, and it is
  73.    zero-terminated. */
  74. uerr_t
  75. fetch_next_header(int fd, char **hdr)
  76. {
  77.    int i, bufsize, res;
  78.    char next;
  79.  
  80.    bufsize = DYNAMIC_LINE_BUFFER;
  81.    *hdr = (char *)nmalloc(bufsize);
  82.    for (i = 0; 1; i++)
  83.    {
  84.       if (i > bufsize - 1)
  85.      *hdr = (char *)nrealloc(*hdr, (bufsize <<= 1));
  86.       res = buf_readchar(fd, *hdr + i);
  87.       if (res == 1)
  88.       {
  89.      if ((*hdr)[i] == '\n')
  90.      {
  91.         if (!(i == 0 || (i == 1 && (*hdr)[0] == '\r')))
  92.         {
  93.            /* If the header is non-empty, we need to check if it
  94.                   continues on to the other line.  We do that by
  95.                   getting the next character without actually
  96.                   downloading it (i.e. peeking it).  */
  97.            res = buf_peek(fd, &next);
  98.            if (res == 0)
  99.           return HEOF;
  100.            else if (res == -1)
  101.           return HERR;
  102.            /*  If the next character is SP or HT, just continue.  */
  103.            if (next == '\t' || next == ' ')
  104.           continue;
  105.         }
  106.         /* The header ends.  */
  107.         (*hdr)[i] = '\0';
  108.         /* Get rid of '\r'. */
  109.         if (i > 0 && (*hdr)[i - 1] == '\r')
  110.            (*hdr)[i - 1] = '\0';
  111.         break;
  112.      }
  113.       }
  114.       else if (res == 0)
  115.      return HEOF;
  116.       else
  117.      return HERR;
  118.    }
  119. #ifdef DEBUG
  120.    if (opt.debug)
  121.       fprintf(opt.lfile, "%s\n", *hdr);
  122. #endif
  123.    return HOK;
  124. }
  125.  
  126. /* Parse the HTTP status line. It is of format:
  127.    HTTP-Version SP Status-Code SP Reason-Phrase
  128.  
  129.    The function returns the status-code, or -1 if the status line is
  130.    malformed. The pointer to reason-phrase is returned in rp. */
  131. int
  132. hparsestatline(const char *hdr, const char **rp)
  133. {
  134.    int mjr, mnr;                /* HTTP major and minor version. */
  135.    int statcode;                /* HTTP status code. */
  136.    const char *p;
  137.  
  138.    *rp = NULL;
  139.    /* The standard format of HTTP-Version is:
  140.       HTTP/x.y, where x is major version, and y is minor version. */
  141.    if (strncmp(hdr, "HTTP/", 5) != 0)
  142.       return -1;
  143.    hdr += 5;
  144.    p = hdr;
  145.    for (mjr = 0; isdigit(*hdr); hdr++)
  146.       mjr = 10 * mjr + (*hdr - '0');
  147.    if (*hdr != '.' || p == hdr)
  148.       return -1;
  149.    ++hdr;
  150.    p = hdr;
  151.    for (mnr = 0; isdigit(*hdr); hdr++)
  152.       mnr = 10 * mnr + (*hdr - '0');
  153.    if (*hdr != ' ' || p == hdr)
  154.       return -1;
  155.    /* Wget will accept only 1.0 and higher HTTP-versions. The value
  156.       of minor version can be safely ignored. */
  157.    if (mjr < 1)
  158.       return -1;
  159.    /* Skip the space. */
  160.    ++hdr;
  161.    if (!(isdigit(*hdr) && isdigit(hdr[1]) && isdigit(hdr[2])))
  162.       return -1;
  163.    statcode = 100 * (*hdr - '0') + 10 * (hdr[1] - '0') + (hdr[2] - '0');
  164.    /* RFC2068 requires a SPC here, even if there is no reason-phrase.
  165.       As some servers/CGI are (incorrectly) setup to drop the SPC,
  166.       we'll be liberal and allow the status line to end here.  */
  167.    if (hdr[3] != ' ')
  168.    {
  169.       if (!hdr[3])
  170.      *rp = hdr + 3;
  171.       else
  172.      return -1;
  173.    }
  174.    else
  175.       *rp = hdr + 4;
  176.    return statcode;
  177. }
  178.  
  179. /* Skip LWS (linear white space), if present.  Returns number of
  180.    characters to skip.  */
  181. int
  182. hskip_lws(const char *hdr)
  183. {
  184.    int i;
  185.    
  186.    for (i = 0;
  187.     *hdr == ' ' || *hdr == '\t' || *hdr == '\r' || *hdr == '\n';
  188.     ++hdr)
  189.       ++i;
  190.    return i;
  191. }
  192.  
  193. /* Return the content length of the document body, if this is
  194.    Content-length header, -1 otherwise. */
  195. long
  196. hgetlen(const char *hdr)
  197. {
  198.    static const int l = 15;           /* strlen("content-length:") */
  199.    long len;
  200.  
  201.    if (strncasecmp(hdr, CONTLEN_H, l))
  202.       return -1;
  203.    hdr += (l + hskip_lws(hdr + l));
  204.    if (!*hdr)
  205.       return -1;
  206.    if (!isdigit(*hdr))
  207.       return -1;
  208.    for (len = 0; isdigit(*hdr); hdr++)
  209.       len = 10 * len + (*hdr - '0');
  210.    return len;
  211. }
  212.  
  213. /* Return the content-range in bytes, as returned by the server, if
  214.    this is Content-range header, -1 otherwise. */
  215. long
  216. hgetrange(const char *hdr)
  217. {
  218.    static const int l = 14;           /* strlen("content-range:") */
  219.    long len;
  220.  
  221.    if (strncasecmp(hdr, CONTRANGE_H, l))
  222.       return -1;
  223.    hdr += (l + hskip_lws(hdr + l));
  224.    if (!*hdr)
  225.       return -1;
  226.    /* Nutscape proxy server sends content-length without "bytes"
  227.       specifier, which is a breach of HTTP/1.1 draft. But heck, I must
  228.       support it... */
  229.    if (!strncasecmp(hdr, "bytes", 5))
  230.    {
  231.       hdr += 5;
  232.       hdr += hskip_lws(hdr);
  233.       if (!*hdr)
  234.      return -1;
  235.    }
  236.    if (!isdigit(*hdr))
  237.       return -1;
  238.    for (len = 0; isdigit(*hdr); hdr++)
  239.       len = 10 * len + (*hdr - '0');
  240.    return len;
  241. }
  242.  
  243. /* Returns the malloc-ed copy of the type of the header hdr, to the
  244.    first ';', or NULL if the header does not begin with CONTTYPE_H
  245.    string. */
  246. char *
  247. hgettype(const char *hdr)
  248. {
  249.    static const int l = 13;           /* strlen("content-type:") */
  250.    char *type;
  251.  
  252.    if (strncasecmp(hdr, CONTTYPE_H, l))
  253.       return NULL;
  254.    hdr += (l + hskip_lws(hdr + l));
  255.    if ((type = strrchr(hdr, ';')) != NULL)
  256.       *type = '\0';
  257.    return nstrdup(hdr);
  258. }
  259.  
  260. /* Returns a malloc-ed copy of the location of the document, if the
  261.    string hdr begins with LOCATION_H, or NULL. */
  262. char *
  263. hgetlocation(const char *hdr)
  264. {
  265.    static const int l = 9;           /* strlen("location:") */
  266.  
  267.    if (strncasecmp(hdr, LOCATION_H, l))
  268.       return NULL;
  269.    hdr += (l + hskip_lws(hdr + l));
  270.    return nstrdup(hdr);
  271. }
  272.  
  273. /* Returns a malloc-ed copy of the last-modified date of the document,
  274.    if the hdr begins with LASTMODIFIED_H. */
  275. char *
  276. hgetmodified(const char *hdr)
  277. {
  278.    static const int l = 14;           /* strlen("last-modified:") */
  279.  
  280.    if (strncasecmp(hdr, LASTMODIFIED_H, l))
  281.       return NULL;
  282.    hdr += (l + hskip_lws(hdr + l));
  283.    return nstrdup(hdr);
  284. }
  285.  
  286. /* Returns 1 if the header is accept-ranges, and it contains the word
  287.    "none", 0 otherwise.  */
  288. int
  289. haccepts_none(const char *hdr)
  290. {
  291.    static const int l = 14;           /* strlen("accept-ranges:") */
  292.  
  293.    if (strncasecmp(hdr, ACCEPTRANGES_H, l))
  294.       return 0;
  295.    hdr += (l + hskip_lws(hdr + l));
  296.    if (strstr(hdr, "none"))
  297.       return 1;
  298.    else
  299.       return 0;
  300. }
  301.  
  302. /* Retrieves a document through HTTP protocol.  It recognizes status
  303.    code, and correctly handles redirections.  It closes the network
  304.    socket.  If it receives an error from the functions below it, it
  305.    will print it if there is enough information to do so (almost
  306.    always), returning the error to the caller (i.e. http_loop).
  307.  
  308.    Various HTTP parameters are stored to hs.  Although it parses the
  309.    response code correctly, it is not used in a sane way.  The caller
  310.    can do that, though.
  311.  
  312.    If u->proxy is non-NULL, the URL u will be taken as a proxy URL,
  313.    and u->proxy->url will be given to the proxy server (bad naming,
  314.    I'm afraid). */
  315. uerr_t
  316. gethttp(urlinfo *u, http_stat_t *hs, int *dt)
  317. {
  318.    char *request, *hdr, *type, *command, *path;
  319.    char *user, *passwd;
  320.    const char *error;
  321.    char *pragma_h, *referer, *useragent, *range, *wwwauth, *remhost;
  322.    char *all_headers;
  323.    int sock, hcount, num_written, all_length, remport, statcode;
  324.    long contlen, contrange;
  325.    urlinfo *ou;
  326.    uerr_t err;
  327.    FILE *fp;
  328.  
  329.    /* Let the others worry about local filename... */
  330.    if (!(*dt & HEAD_ONLY))
  331.       assert(u->local != NULL);
  332.  
  333.    /* Initialize certain elements of struct hstat. */
  334.    hs->len = 0L;
  335.    hs->contlen = -1;
  336.    hs->res = -1;
  337.    hs->newloc = NULL;
  338.    hs->remote_time = NULL;
  339.    hs->error = NULL;
  340.  
  341.    /* Which structure to use to yield the original URL data. */
  342.    if (u->proxy)
  343.       ou = u->proxy;
  344.    else
  345.       ou = u;
  346.  
  347.    /* First: establish the connection. */
  348.    if (opt.verbose)
  349.       fprintf(opt.lfile, "Connecting to %s:%hu... ", u->host, u->port);
  350.    err = make_connection(&sock, u->host, u->port);
  351.    switch (err)
  352.    {
  353.       case HOSTERR:
  354.      if (!opt.quiet)
  355.      {
  356.         if (opt.verbose)
  357.            fprintf(opt.lfile, "\n");
  358.         fprintf(opt.lfile, "%s: %s.\n", u->host, herrmsg(h_errno));
  359.      }
  360.      return HOSTERR;
  361.      break;
  362.       case CONSOCKERR:
  363.      if (!opt.quiet)
  364.      {
  365.         if (opt.verbose)
  366.            fprintf(opt.lfile, "\n");
  367.         fprintf(opt.lfile, "socket: %s\n", mystrerror(errno));
  368.      }
  369.      return CONSOCKERR;
  370.      break;
  371.       case CONREFUSED:
  372.      if (!opt.quiet)
  373.      {
  374.         if (opt.verbose)
  375.            fprintf(opt.lfile, "\n");
  376.         fprintf(opt.lfile, "Connection to %s:%hu refused.\n", u->host, u->port);
  377.      }
  378.      CLOSE(sock);
  379.      return CONREFUSED;
  380.       case CONERROR:
  381.      if (!opt.quiet)
  382.      {
  383.         if (opt.verbose)
  384.            fprintf(opt.lfile, "\n");
  385.         fprintf(opt.lfile, "connect: %s\n", mystrerror(errno));
  386.      }
  387.      CLOSE(sock);
  388.      return CONERROR;
  389.      break;
  390.       case NOCONERROR:
  391.      /* Everything is fine! */
  392.      if (opt.verbose)
  393.         fprintf(opt.lfile, "connected!\n");
  394.      break;
  395.       default:
  396.      assert(0);
  397.      break;
  398.    } /* switch */
  399.  
  400.    if (u->proxy)
  401.       path = u->proxy->url;
  402.    else
  403.       path = u->path;
  404.    command = (*dt & HEAD_ONLY) ? "HEAD" : "GET";
  405.    referer = NULL;
  406.    if (ou->referer)
  407.    {
  408.       referer = (char *)nmalloc(9 + strlen(ou->referer) + 3);
  409.       sprintf(referer, "Referer: %s\r\n", ou->referer);
  410.    }
  411.    if (*dt & SEND_NOCACHE)
  412.       pragma_h = "Pragma: no-cache\r\n";
  413.    else
  414.       pragma_h = "";
  415.    if (hs->restval)
  416.    {
  417.       range = (char *)nmalloc(13 + numdigit(hs->restval) + 4);
  418.       sprintf(range, "Range: bytes=%ld-\r\n", hs->restval);
  419.    }
  420.    else
  421.       range = NULL;
  422.    useragent = opt.useragent ? opt.useragent : version_string;
  423.    /* Construct the authentication, if userid is present. */
  424.    user = ou->user;
  425.    passwd = ou->passwd;
  426.    search_netrc(u->host, (const char **)&user, (const char **)&passwd, 0);
  427.    user = user ? user : opt.http_user;
  428.    passwd = passwd ? passwd : opt.http_passwd;
  429.  
  430.    if (user && passwd)
  431.    {
  432.       char *t1, *t2;
  433.  
  434.       t1 = (char *)nmalloc(strlen(user) + 1 + 2 * strlen(passwd));
  435.       sprintf(t1, "%s:%s", user, passwd);
  436.       t2 = base64_encode_line(t1);
  437.       free(t1);
  438.       wwwauth = (char *)nmalloc(strlen(t2) + 24);
  439.       sprintf(wwwauth, "Authorization: Basic %s\r\n", t2);
  440.       free(t2);
  441.    }
  442.    else
  443.       wwwauth = NULL;
  444.    remhost = ou->host;
  445.    remport = ou->port;
  446.    /* Allocate the memory for the request. */
  447.    request = (char *)nmalloc(strlen(command) + strlen(path)
  448.                  + strlen(useragent)
  449.                  + strlen(remhost) + numdigit(remport)
  450.                  + strlen(HTTP_ACCEPT)
  451.                  + (referer ? strlen(referer) : 0)
  452.                  + (wwwauth ? strlen(wwwauth) : 0)
  453.                  + (range ? strlen(range) : 0)
  454.                  + strlen(pragma_h)
  455.                  + (opt.user_header ? strlen(opt.user_header) : 0)
  456.                  + 60);
  457.    /* Construct the request. */
  458.    sprintf(request, "%s %s HTTP/1.0\r\nUser-Agent: %s\r\nHost: %s:%d\r\nAccept: %s\r\n%s%s%s%s%s\r\n",
  459.        command, path, useragent, remhost, remport, HTTP_ACCEPT, referer ?
  460.        referer : "", wwwauth ? wwwauth : "", range ? range : "",
  461.        pragma_h, opt.user_header ? opt.user_header : "");
  462.    /* Free the temporary memory. */
  463.    if (referer)
  464.       free(referer);
  465.    if (range)
  466.       free(range);
  467.    if (wwwauth)
  468.       free(wwwauth);
  469.  
  470.    DEBUGP(request);
  471.  
  472.    /* Send the request to server */
  473.    num_written = iwrite(sock, request, strlen(request));
  474.    if (num_written != strlen(request))
  475.    {
  476.       if (opt.verbose)
  477.      fprintf(opt.lfile, "Failed writing HTTP request.\n");
  478.       free(request);
  479.       CLOSE(sock);
  480.       return WRITEFAILED;
  481.    }
  482.    if (opt.verbose)
  483.       fprintf(opt.lfile, "%s request sent, fetching headers... ",
  484.           u->proxy ? "HTTP proxy" : "HTTP");
  485.    free(request);
  486.    contlen = contrange = -1;
  487.    type = NULL;
  488.    statcode = -1;
  489.    *dt &= ~RETROKF;
  490.  
  491.    /* Since this is a new connection, we may safely discard anything
  492.       left in the buffer. */
  493.    buf_discard();
  494.    
  495.    all_headers = NULL;
  496.    all_length = 0;
  497.    /* Header-fetching loop. */
  498.    hcount = 0;
  499.    for (;;)
  500.    {
  501.       ++hcount;
  502.       /* Get the header. */
  503.       err = fetch_next_header(sock, &hdr);
  504.       /* Check for errors. */
  505.       if (err == HEOF)
  506.       {
  507.      if (!opt.quiet)
  508.      {
  509.         if (opt.verbose)
  510.            fprintf(opt.lfile, "\n");
  511.         fprintf(opt.lfile, "End of file while parsing headers.\n");
  512.      }
  513.      free(hdr);
  514.      if (type)
  515.         free(type);
  516.      if (hs->newloc)
  517.         free(hs->newloc);
  518.      if (all_headers)
  519.         free(all_headers);
  520.      CLOSE(sock);
  521.      return HEOF;
  522.       }
  523.       else if (err == HERR)
  524.       {
  525.      if (!opt.quiet)
  526.      {
  527.         if (opt.verbose)
  528.            fprintf(opt.lfile, "\n");
  529.         fprintf(opt.lfile, "Read error (%s) in headers.\n",
  530.             mystrerror(errno));
  531.      }
  532.      free(hdr);
  533.      if (type)
  534.         free(type);
  535.      if (hs->newloc)
  536.         free(hs->newloc);
  537.      if (all_headers)
  538.         free(all_headers);
  539.      CLOSE(sock);
  540.      return HERR;
  541.       }
  542.  
  543.       /* If the headers are to be saved to a file later, save them to
  544.      memory now. */
  545.       if (opt.save_headers)
  546.       {
  547.      int lh = strlen(hdr);
  548.      all_headers = (char *)nrealloc(all_headers, all_length + lh + 2);
  549.      memcpy(all_headers + all_length, hdr, lh);
  550.      all_length += lh;
  551.      all_headers[all_length++] = '\n';
  552.      all_headers[all_length] = '\0';
  553.       }
  554.       
  555.       /* Exit on empty header. */
  556.       if (!*hdr)
  557.       {
  558.      free(hdr);
  559.      break;
  560.       }
  561.  
  562.       /* Print the header if necessary. */
  563.       if (opt.verbose && opt.server_response)
  564.      fprintf(opt.lfile, "\n%d %s", hcount, hdr);
  565.  
  566.       /* Check for errors documented in the first header. */
  567.       if (hcount == 1)
  568.       {
  569.      /* Parse the first line of server response. */
  570.      statcode = hparsestatline(hdr, &error);
  571.      hs->statcode = statcode;
  572.      /* Store the descriptive response. */
  573.      if (statcode == -1) /* malformed request */
  574.         hs->error = nstrdup("UNKNOWN");
  575.      else if (!*error)
  576.         hs->error = nstrdup("(no description)");
  577.      else
  578.         hs->error = nstrdup(error);
  579.       }
  580.       /* Try getting content-length. */
  581.       if (contlen == -1 && !opt.ignore_length)
  582.      contlen = hgetlen(hdr);
  583.       /* Try getting content-type. */
  584.       if (!type)
  585.      type = hgettype(hdr);
  586.       /* Try getting location. */
  587.       if (!hs->newloc)
  588.      hs->newloc = hgetlocation(hdr);
  589.       /* Try getting last-modified. */
  590.       if (!hs->remote_time)
  591.      hs->remote_time = hgetmodified(hdr);
  592.       /* Check for accept-ranges header.  If it contains the word
  593.      `none', disable the ranges.  */
  594.       if (*dt & ACCEPTRANGES)
  595.      if (haccepts_none(hdr))
  596.         *dt &= ~ACCEPTRANGES;
  597.       /* Try getting content-range. */
  598.       if (contrange == -1)
  599.      contrange = hgetrange(hdr);
  600.       /* Free the current header. */
  601.       free(hdr);
  602.    } /* for (;;) */
  603.  
  604.    /* 20x responses are counted among successful by default. */
  605.    if (H_20X(statcode))
  606.       *dt |= RETROKF;
  607.  
  608.    if (type)
  609.       (!strncasecmp(type, TEXTHTML_S, strlen(TEXTHTML_S))) ?
  610.      (*dt |= TEXTHTML) : (*dt &= ~TEXTHTML);
  611.    else
  612.       *dt &= ~TEXTHTML; /* NOT text/html by default */
  613.  
  614.    if (contrange == -1)
  615.       hs->restval = 0;
  616.    else if (contrange != hs->restval ||
  617.         (H_PARTIAL(statcode) && contrange == -1))
  618.    {
  619.       /* This means the whole request was somehow misunderstood by the
  620.      server. Bail out. */
  621.       if (type)
  622.      free(type);
  623.       if (hs->newloc)
  624.      free(hs->newloc);
  625.       if (all_headers)
  626.      free(all_headers);
  627.       CLOSE(sock);
  628.       return RANGEERR;
  629.    }
  630.  
  631.    if (hs->restval)
  632.    {
  633.       if (contlen != -1)
  634.      contlen += contrange;
  635.       else
  636.      contrange = -1;        /* If conent-length was not sent,
  637.                    content-range will be ignored. */
  638.    }
  639.    hs->contlen = contlen;
  640.    if (opt.verbose)
  641.    {
  642.       if (!opt.server_response)
  643.       fprintf(opt.lfile, "done.");
  644.       fprintf(opt.lfile, "\n");
  645.    }
  646.    /* Return if redirected.  */
  647.    if (H_REDIRECTED(statcode) || statcode == HTTP_MULTIPLE_CHOICES)
  648.    {
  649.       /* RFC2068 says that in case of the 300 (multiple choices)
  650.      response, the server can output a preferred URL through
  651.      `Location' header; otherwise, the request should be treated
  652.      like GET.  So, if the location is set, it will be a
  653.      redirection; otherwise, just proceed normally.  */
  654.       if (statcode == HTTP_MULTIPLE_CHOICES && !hs->newloc)
  655.      *dt |= RETROKF;
  656.       else
  657.       {
  658.      fprintf(opt.lfile, "Location: %s%s\n",
  659.          hs->newloc ? hs->newloc : "unspecified",
  660.          hs->newloc ? " [following]" : "");
  661.      CLOSE(sock);
  662.      if (all_headers)
  663.         free(all_headers);
  664.      if (type)
  665.         free(type);
  666.      return NEWLOCATION;
  667.       }
  668.    }
  669.    if (opt.verbose)
  670.    {
  671.       if ((*dt & RETROKF) && !opt.server_response)
  672.       {
  673.      /* No need tp print this output if the body won't be
  674.         downloaded at all, or if the original server response is
  675.         printed.  */
  676.      fprintf(opt.lfile, "Length: ");
  677.      if (contlen != -1)
  678.      {
  679.         fprintf(opt.lfile, "%s", legible(contlen));
  680.         if (contrange != -1)
  681.            fprintf(opt.lfile, " (%s to go)", legible(contlen - contrange));
  682.      }
  683.      else
  684.         fprintf(opt.lfile, opt.ignore_length ? "ignored" : "unspecified");
  685.      if (type)
  686.         fprintf(opt.lfile, " [%s]\n", type);
  687.      else
  688.         fprintf(opt.lfile, "\n");
  689.       }
  690.    }
  691.    if (type)
  692.       free(type);
  693.    type = NULL;                 /* We don't need it any more. */
  694.  
  695.    /* Return if we have no intention of further downloading.  */
  696.    if (!(*dt & RETROKF) || (*dt & HEAD_ONLY))
  697.    {
  698.       /* In case someone cares to look... */
  699.       hs->len = 0L;
  700.       hs->res = 0;
  701.       if (all_headers)
  702.      free(all_headers);
  703.       if (type)
  704.      free(type);
  705.       CLOSE(sock);
  706.       return RETRFINISHED;
  707.    }
  708.  
  709.    /* Open the local file.  */
  710.    if (!opt.dfp)
  711.    {
  712.       mkalldirs(u->local);
  713.       fp = fopen(u->local, hs->restval ? "ab" : "wb");
  714.       if (!fp)
  715.       {
  716.      if (!opt.quiet)
  717.         fprintf(opt.lfile, "%s: %s\n", u->local, mystrerror(errno));
  718.      CLOSE(sock);
  719.      if (all_headers)
  720.         free(all_headers);
  721.      return FOPENERR;
  722.       }
  723.    }
  724.    else                      /* opt.dfp */
  725.       fp = opt.dfp;
  726.  
  727.    if (opt.save_headers)
  728.       fwrite(all_headers, 1, all_length, fp);
  729.    reset_timer();
  730.    /* Get the contents of the document. */
  731.    hs->res = get_contents(sock, fp, &hs->len, hs->restval, 0);
  732.    hs->dltime = elapsed_time();
  733.    if (!opt.dfp)
  734.       fclose(fp);
  735.    else
  736.       fflush(fp);
  737.    if (all_headers)
  738.       free(all_headers);
  739.    CLOSE(sock);
  740.    if (hs->res == -2)
  741.       return FWRITEERR;
  742.    return RETRFINISHED;
  743. }
  744.  
  745. /* The genuine HTTP loop! This is the part where the retrieval is
  746.    retried, and retried, and retried, and... */
  747. uerr_t
  748. http_loop(urlinfo *u, char **newloc, int *dt)
  749. {
  750.    static int first_retrieval = 1;
  751.    
  752.    int count;
  753.    int use_ts, got_head = 0;    /* Time-stamping info. */
  754.    char *tms, *suf, *locf, *tmrate;
  755.    uerr_t err;
  756.    time_t tml = -1, tmr = -1;   /* Local and remote time-stamps. */
  757.    long local_size = 0;         /* The size of the local file. */
  758.    http_stat_t hstat;           /* HTTP status. */
  759.    struct stat st;
  760.    void my_touch PARAMS((char *, time_t));
  761.  
  762.    *newloc = NULL;
  763.    /* Warn on wildcard usage in HTTP.  Don't use has_wildcards because
  764.       it would also warn on '?', and we don't what that because of
  765.       CGI. */
  766.    if (opt.verbose && strchr(u->url, '*'))
  767.       fprintf(opt.lfile, "Warning: wildcards not supported in HTTP.\n");
  768.    /* Determine the local filename. */
  769.    if (!u->local)
  770.    {
  771.       if (!opt.timestamping || opt.recursive)
  772.      u->local = url_filename(u->proxy ? u->proxy : u);
  773.       else /* opt.timestamping && !recursive */
  774.       {
  775.      if (*(u->proxy ? u->proxy->file : u->file))
  776.         u->local = nstrdup(u->proxy ? u->proxy->file : u->file);
  777.      else
  778.         u->local = nstrdup("index.html");
  779.       }
  780.    }
  781.  
  782.    if (!opt.output_document)
  783.       locf = u->local;
  784.    else
  785.       locf = opt.output_document;
  786.  
  787.    if (opt.noclobber && exists(u->local))
  788.    {
  789.       /* If opt.noclobber is turned on and file already exists, do not
  790.      retrieve the file */
  791.       if (opt.verbose)
  792.      fprintf(opt.lfile, "File `%s' already there, will not retrieve.\n",
  793.          u->local);
  794.       /* If the file is there, we suppose it's retrieved OK. */
  795.       *dt |= RETROKF;
  796.       /* If its suffix is "html" or (yuck!) "htm", we suppose it's
  797.      text/html, a harmless lie. */
  798.       if (((suf = suffix(u->local)) != NULL)
  799.       && (!strcmp(suf, "html") || !strcmp(suf, "htm")))
  800.      *dt |= TEXTHTML;
  801.       free(suf);
  802.       /* Another harmless lie: */
  803.       return RETROK;
  804.    }
  805.    
  806.    use_ts = 0;
  807.    if (opt.timestamping)
  808.    {
  809.       if (stat(u->local, &st) == 0)
  810.       {
  811.      use_ts = 1;
  812.      tml = st.st_mtime;
  813.      local_size = st.st_size;
  814.      got_head = 0;
  815.       }
  816.    }
  817.    /* Reset the counter. */
  818.    count = 0;
  819.    *dt = 0 | ACCEPTRANGES;
  820.    /* THE loop */
  821.    do
  822.    {
  823.       /* Increment the pass counter. */
  824.       ++count;
  825.       /* Wait before the retrieval (unless this is the very first
  826.      retrieval). */
  827.       if (!first_retrieval && opt.wait)
  828.      sleep(opt.wait);
  829.       if (first_retrieval)
  830.      first_retrieval = 0;
  831.       /* Get the current time string. */
  832.       tms = time_str(NULL);
  833.       /* Print fetch message, if opt.verbose. */
  834.       if (opt.verbose)
  835.       {
  836.      char *hurl = str_url(u->proxy ? u->proxy : u, 1);
  837.      char tmp[15];
  838.      strcpy(tmp, "        ");
  839.      if (count > 1)
  840.         sprintf(tmp, "(try:%2d)", count);
  841.      fprintf(opt.lfile,
  842.          "--%s--  %s\n  %s => `%s'\n",
  843.          tms, hurl, tmp, locf);
  844.      free(hurl);
  845.       }
  846.  
  847.       /* Default document type is empty.  However, if spider mode is
  848.      on or time-stamping is employed, HEAD_ONLY commands is
  849.      encoded within *dt. */
  850.       if (opt.spider || (use_ts && !got_head))
  851.      *dt |= HEAD_ONLY;
  852.       else
  853.      *dt &= ~HEAD_ONLY;
  854.       /* Assume no restarting. */
  855.       hstat.restval = 0L;
  856.       /* Decide whether or not to restart. */
  857.       if (((count > 1 && (*dt & ACCEPTRANGES)) || opt.always_rest)
  858.       && exists(u->local))
  859.      if (stat(u->local, &st) == 0)
  860.         hstat.restval = st.st_size;
  861.       /* Decide whether to send the no-cache directive. */
  862.       if (u->proxy && (count > 1 || (opt.proxy_cache == 0)))
  863.      *dt |= SEND_NOCACHE;
  864.       else
  865.      *dt &= ~SEND_NOCACHE;
  866.       
  867.       /* Try fetching the document, or at least its head. :-) */
  868.       err = gethttp(u, &hstat, dt);
  869.       /* Time? */
  870.       tms = time_str(NULL);
  871.       /* Get the new location (with or without the redirection).  */
  872.       if (hstat.newloc)
  873.      *newloc = nstrdup(hstat.newloc);
  874.       switch (err)
  875.       {
  876.      case HERR: case HEOF: case CONSOCKERR: case CONCLOSED:
  877.      case CONERROR: case READERR: case WRITEFAILED:
  878.      case RANGEERR:
  879.         /* Non-fatal errors continue executing the loop, which
  880.            will bring them to "while" statement at the end, to
  881.            judge whether the number of tries was exceeded. */
  882.         FREEHSTAT(hstat);
  883.         printwhat(count, opt.ntry);
  884.         continue;
  885.         break;
  886.      case HOSTERR: case CONREFUSED: case PROXERR:
  887.         /* Fatal errors just return from the function. */
  888.         FREEHSTAT(hstat);
  889.         return err;
  890.         break;
  891.      case FWRITEERR: case FOPENERR:
  892.         /* Another fatal error. */
  893.         if (!opt.quiet)
  894.         {
  895.            if (opt.verbose)
  896.           fprintf(opt.lfile, "\n");
  897.            fprintf(opt.lfile, "Cannot write to `%s' (%s).\n",
  898.                u->local, mystrerror(errno));
  899.         }
  900.         FREEHSTAT(hstat);
  901.         return err;
  902.         break;
  903.      case NEWLOCATION:
  904.         /* Return the new location to the caller. */
  905.         if (!hstat.newloc)
  906.         {
  907.            if (!opt.quiet)
  908.           fprintf(opt.lfile,
  909.               "ERROR: Redirection (%d) without location.\n",
  910.               hstat.statcode);
  911.            return WRONGCODE;
  912.         }
  913.         FREEHSTAT(hstat);
  914.         return NEWLOCATION;
  915.         break;
  916.      case RETRFINISHED:
  917.         /* Deal with you later. */
  918.         break;
  919.      default:
  920.         /* All possibilities should have been exhausted. */
  921.         assert(0);
  922.       }
  923.       if (!(*dt & RETROKF))
  924.       {
  925.      if (!opt.quiet)
  926.      {
  927.         fprintf(opt.lfile, "%s ERROR %d: %s.\n", tms, hstat.statcode,
  928.             hstat.error);
  929.         if (opt.verbose)
  930.            fputc('\n', opt.lfile);
  931.      }
  932.      FREEHSTAT(hstat);
  933.      return WRONGCODE;
  934.       }
  935.  
  936.       /* Did we get the time-stamp?  */
  937.       if (!got_head)
  938.       {
  939.      if (opt.timestamping && !hstat.remote_time)
  940.      {
  941.         if (!opt.quiet)
  942.            fprintf(opt.lfile, "Last-modified header missing -- time-stamps turned off.\n");
  943.      }
  944.      else if (hstat.remote_time)
  945.      {
  946.         /* Convert the date-string into struct tm. */
  947.         tmr = http_atotm(hstat.remote_time);
  948.         if (tmr == -1)
  949.            if (opt.verbose)
  950.           fprintf(opt.lfile, "Last-modified header invalid -- time-stamp ignored.\n");
  951.      }
  952.       }
  953.  
  954.       /* The time-stamping section. */
  955.       if (use_ts)
  956.       {
  957.      got_head = 1;
  958.      *dt &= ~HEAD_ONLY;
  959.      use_ts = 0;            /* No more time-stamping. */
  960.      count = 0;             /* The retrieve count for HEAD is
  961.                    reset. */
  962.      if (hstat.remote_time && tmr != -1)
  963.      {
  964.         /* Now time-stamping can be used validly.  Time -
  965.            stamping means that if the sizes of the local and
  966.            remote file match, and local file is newer than the
  967.            remote file, it will not be retrieved. Otherwise,
  968.            the normal download procedure is resumed. */
  969.         if (local_size == hstat.contlen && tml >= tmr)
  970.         {
  971.            if (opt.verbose)
  972.           fprintf(opt.lfile, "Local file `%s' is more recent, not retrieving.\n\n", u->local);
  973.            FREEHSTAT(hstat);
  974.            return RETROK;
  975.         }
  976.         else if (local_size != hstat.contlen)
  977.         {
  978.            if (opt.verbose)
  979.           fprintf(opt.lfile, "The sizes do not match (local %ld), retrieving.\n", local_size);
  980.         }
  981.         else
  982.         {
  983.            if (opt.verbose)
  984.           fprintf(opt.lfile, "Remote file is newer, retrieving.\n");
  985.         }
  986.      }
  987.      FREEHSTAT(hstat);
  988.      continue;
  989.       } /* use_ts */
  990.       if (!opt.dfp
  991.       && (tmr != -1) && !opt.spider &&
  992.       ((hstat.len == hstat.contlen) ||
  993.        ((hstat.res == 0) &&
  994.         ((hstat.contlen == -1) ||
  995.          (hstat.len >= hstat.contlen && !opt.kill_longer)))))
  996.       {
  997.      my_touch(u->local, tmr);
  998.       }
  999.       /* End of time-stamping section. */
  1000.  
  1001.       if (opt.spider)
  1002.       {
  1003.      fprintf(opt.lfile, "%d %s\n\n", hstat.statcode, hstat.error);
  1004.      return RETROK;
  1005.       }
  1006.  
  1007.       /* It is now safe to free the remainder of hstat, since the
  1008.      strings within it will no longer be used. */
  1009.       FREEHSTAT(hstat);
  1010.  
  1011.       tmrate = rate(hstat.len - hstat.restval, hstat.dltime);
  1012.  
  1013.       if (hstat.len == hstat.contlen)
  1014.       {
  1015.      if (*dt & RETROKF)
  1016.      {
  1017.         if (opt.verbose)
  1018.            fprintf(opt.lfile, "%s (%s) - `%s' saved [%ld/%ld]\n\n",
  1019.                tms, tmrate, locf, hstat.len, hstat.contlen);
  1020.         else if (!opt.quiet)
  1021.            fprintf(opt.lfile, "%s URL:%s [%ld/%ld] -> \"%s\" [%d]\n",
  1022.                tms, u->url, hstat.len, hstat.contlen, locf, count);
  1023.      }
  1024.      ++opt.numurls;
  1025.      opt.downloaded += hstat.len;
  1026.      return RETROK;
  1027.       }
  1028.       else if (hstat.res == 0) /* No read error */
  1029.       {
  1030.      if (hstat.contlen == -1)  /* We don't know how much we were
  1031.                       supposed to get, so... */
  1032.      {
  1033.         if (*dt & RETROKF)
  1034.         {
  1035.            if (opt.verbose)
  1036.           fprintf(opt.lfile, "%s (%s) - `%s' saved [%ld]\n\n",
  1037.               tms, tmrate, locf, hstat.len);
  1038.            else if (!opt.quiet)
  1039.           fprintf(opt.lfile, "%s URL:%s [%ld] -> \"%s\" [%d]\n",
  1040.               tms, u->url, hstat.len, locf, count);
  1041.         }
  1042.         ++opt.numurls;
  1043.         opt.downloaded += hstat.len;
  1044.         return RETROK;
  1045.      }
  1046.      else if (hstat.len < hstat.contlen) /* Meaning we lost the
  1047.                         connection too soon */
  1048.      {
  1049.         if (opt.verbose)
  1050.         {
  1051.            fprintf(opt.lfile, "%s (%s) - Connection closed at byte %ld. ",
  1052.                tms, tmrate, hstat.len);
  1053.            printwhat(count, opt.ntry);
  1054.         }
  1055.         continue;
  1056.      }
  1057.      else if (!opt.kill_longer) /* Meaning we got more than expected */
  1058.      {
  1059.         if (opt.verbose)
  1060.            fprintf(opt.lfile, "%s (%s) - `%s' saved [%ld/%ld])\n\n",
  1061.                tms, tmrate, locf, hstat.len, hstat.contlen);
  1062.         else if (!opt.quiet)
  1063.            fprintf(opt.lfile, "%s URL:%s [%ld/%ld] -> \"%s\" [%d]\n",
  1064.                tms, u->url, hstat.len, hstat.contlen, locf, count);
  1065.         ++opt.numurls;
  1066.         opt.downloaded += hstat.len;
  1067.         return RETROK;
  1068.      }
  1069.      else /* The same, but not accepted */
  1070.      {
  1071.         if (opt.verbose)
  1072.         {
  1073.            fprintf(opt.lfile,
  1074.                "%s (%s) - Connection closed at byte %ld/%ld. ",
  1075.                tms, tmrate, hstat.len, hstat.contlen);
  1076.            printwhat(count, opt.ntry);
  1077.         }
  1078.         continue;
  1079.      }
  1080.       }
  1081.       else /* Now hstat.res can only be -1 */
  1082.       {
  1083.      if (hstat.contlen == -1)
  1084.      {
  1085.         if (opt.verbose)
  1086.         {
  1087.            fprintf(opt.lfile,
  1088.                "%s (%s) - Read error at byte %ld (%s).",
  1089.                tms, tmrate, hstat.len, mystrerror(errno));
  1090.            printwhat(count, opt.ntry);
  1091.         }
  1092.         continue;
  1093.      }
  1094.      else /* hstat.res == -1 and contlen is given */
  1095.      {
  1096.         if (opt.verbose)
  1097.         {
  1098.            fprintf(opt.lfile,
  1099.                "%s (%s) - Read error at byte %ld/%ld (%s). ",
  1100.                tms, tmrate, hstat.len, hstat.contlen,
  1101.                mystrerror(errno));
  1102.            printwhat(count, opt.ntry);
  1103.         }
  1104.         continue;
  1105.      }
  1106.       }
  1107.       /* not reached */
  1108.       break;
  1109.    } while (!opt.ntry || (count < opt.ntry));
  1110.    return TRYLIMEXC;
  1111. }
  1112.  
  1113. /* Encode a zero-terminated string in base64.  Returns the malloc-ed
  1114.    encoded line.  This is useful for HTTP only.
  1115.  
  1116.    Note that the string may not contain NUL characters.  */
  1117. char *
  1118. base64_encode_line(const char *s)
  1119. {
  1120.    /* Conversion table. */
  1121.    static char tbl[64] = {
  1122.       'A','B','C','D','E','F','G','H',
  1123.       'I','J','K','L','M','N','O','P',
  1124.       'Q','R','S','T','U','V','W','X',
  1125.       'Y','Z','a','b','c','d','e','f',
  1126.       'g','h','i','j','k','l','m','n',
  1127.       'o','p','q','r','s','t','u','v',
  1128.       'w','x','y','z','0','1','2','3',
  1129.       '4','5','6','7','8','9','+','/'
  1130.    };
  1131.    int len, i;
  1132.    char *res;
  1133.    unsigned char *p;
  1134.  
  1135.    len = strlen(s);
  1136.    res = (char *)nmalloc(4 * ((len + 2) / 3) + 1);
  1137.    p = (unsigned char *)res;
  1138.    /* Transform the 3x8 bits to 4x6 bits, as required by
  1139.       base64.  */
  1140.    for (i = 0; i < len; i += 3)
  1141.    {
  1142.       *p++ = tbl[s[0] >> 2];
  1143.       *p++ = tbl[((s[0] & 3) << 4) + (s[1] >> 4)];
  1144.       *p++ = tbl[((s[1] & 0xf) << 2) + (s[2] >> 6)];
  1145.       *p++ = tbl[s[2] & 0x3f];
  1146.       s += 3;
  1147.    }
  1148.    /* Pad the result if necessary... */
  1149.    if (i == len + 1)
  1150.       *(p - 1) = '=';
  1151.    else if (i == len + 2)
  1152.       *(p - 1) = *(p - 2) = '=';
  1153.    /* ...and zero-teminate it.  */
  1154.    *p = '\0';
  1155.    return res;
  1156. }
  1157.  
  1158. /* Converts struct tm to time_t, assuming the data in tm is UTC rather
  1159.    than local timezone (as mktime assumes).
  1160.    
  1161.    Contributed by Roger Beeman <beeman@cisco.com>.  */
  1162. time_t
  1163. mktime_from_utc(struct tm *t)
  1164. {
  1165.    time_t tl, tb;
  1166.  
  1167.    tl = mktime(t);
  1168.    tb = mktime(gmtime(&tl));                               
  1169.    return (tl <= tb ? (tl + (tl - tb)) : (tl - (tb - tl)));
  1170. }
  1171.  
  1172. /* Converts ASCII time to time_t.  The time can be in three formats
  1173.    allowed for HTTP servers to send, as per RFC2068 -- RFC1123-date,
  1174.    RFC850-date or asctime-date.
  1175.  
  1176.    strptime() is used to recognize various dates, which makes it a
  1177.    little bit slacker than the RFC1123/RFC850/asctime (e.g. it always
  1178.    allows shortened dates and months, one-digit days, etc.).  It also
  1179.    allows more than one space anywhere where the specs require one SP.
  1180.    The routine should probably be even slacker (RFC2068 recommends
  1181.    this), but I do not have the time to write one.
  1182.  
  1183.    Returns the computed time_t representation, or -1 if all the
  1184.    schemes fail.  */
  1185. time_t
  1186. http_atotm(char *s)
  1187. {
  1188.    struct tm t;
  1189.  
  1190.    t.tm_isdst = -1;
  1191.  
  1192.    /* NOTE: We don't use `%n' for white space, as OSF's strptime uses
  1193.       it to eat all white space up to (and including) a newline, and
  1194.       the function fails (!) if there is no newline.
  1195.  
  1196.       Let's hope all strptime-s use ` ' to skipp *all* whitespace
  1197.       instead of just one (it works that way on all the systems I've
  1198.       tested it on). */
  1199.    
  1200.    /* Let's try RFC1123 date. */
  1201.    if (strptime(s, "%a, %d %b %Y %T", &t))
  1202.       return mktime_from_utc(&t);
  1203.    /* RFC850 date. */
  1204.    if (strptime(s, "%a, %d-%b-%y %T", &t))
  1205.       return mktime_from_utc(&t);
  1206.    /* asctime date. */
  1207.    if (strptime(s, "%a %b %d %T %Y", &t))
  1208.       return mktime_from_utc(&t);
  1209.    /* Failure. */
  1210.    return -1;
  1211. }
  1212.